package top.saplf.sileny.main.home

import android.Manifest
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.support.design.widget.BaseTransientBottomBar
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.support.design.widget.TabLayout.Tab
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.WindowManager
import com.jakewharton.rxbinding2.view.RxView
import com.jakewharton.rxbinding2.view.clicks
import com.tbruyelle.rxpermissions2.RxPermissions
import kotlinx.android.synthetic.main.activity_main.*
import top.saplf.sileny.R
import top.saplf.sileny.base.ui.IActivity
import top.saplf.sileny.editor.home.EditorIndexFragment
import top.saplf.sileny.ext.TabSelectedAction
import top.saplf.sileny.ext.addListenerStopListener
import top.saplf.sileny.ext.addOnTabSelectedListener
import top.saplf.sileny.ext.blur
import top.saplf.sileny.player.home.LocalMusicIndexFragment
import top.saplf.sileny.reader.main.ReaderIndexFragment
import top.saplf.library.ui.FloatingActionMenu.LayoutParams as FamLayoutParams

class MainActivity : AppCompatActivity(), IActivity, ViewPager.OnPageChangeListener {

    companion object {
        private const val ANIMATION_DELAY = 180L
    }

    private val readerStr by lazy { getString(R.string.header_0_reader) }
    private val writerStr by lazy { getString(R.string.header_0_writer) }
    private val playerStr by lazy { getString(R.string.header_0_player) }

    private val rxPermissions: RxPermissions by lazy { RxPermissions(this@MainActivity) }
    private val tabSelectedAction: TabSelectedAction by lazy { { _: Tab -> actionMenu.hideMenu() } }
    private val blurStartAnimator: ValueAnimator by lazy {
        ObjectAnimator.ofFloat(shade, "alpha", 0f, 1f).apply { duration = ANIMATION_DELAY }
    }
    private val blurEndAnimator: ValueAnimator by lazy {
        ObjectAnimator.ofFloat(shade, "alpha", 1f, 0f).apply {
            duration = ANIMATION_DELAY
            addListenerStopListener {
                shade.setImageBitmap(null)
                shade.visibility = GONE
            }
        }
    }
    private val forceAnimation: Snackbar.() -> Unit by lazy {
        { _: Snackbar ->
            // fixme use reflection to force enable snackbar's appear animation
            val accessibilityManagerField = BaseTransientBottomBar::class.java.getDeclaredField("mAccessibilityManager")
            accessibilityManagerField.isAccessible = true
            val accessibilityManager = accessibilityManagerField.get(this)
            val isEnabledField = accessibilityManager::class.java.getDeclaredField("mIsEnabled")
            isEnabledField.isAccessible = true
            isEnabledField.setBoolean(accessibilityManager, false)
            accessibilityManagerField.set(this, accessibilityManager)
        }
    }
    private val noPermissionSnack: Snackbar by lazy {
        Snackbar
                .make(coordinator, R.string.read_storage_permission, Snackbar.LENGTH_SHORT)
                .apply(forceAnimation)
    }
    val loadErrorSnack: Snackbar by lazy {
        Snackbar
                .make(coordinator, R.string.load_error, Snackbar.LENGTH_SHORT)
                .apply(forceAnimation)
    }

    private val readerPage by lazy { ReaderIndexFragment.getInstance() }
    private val editorPage by lazy { EditorIndexFragment.getInstance() }
    private val playerPage by lazy { LocalMusicIndexFragment.getInstance() }

    override fun onLayoutRes() = R.layout.activity_main

    override fun onViewCreated(savedInstanceState: Bundle?) {
        val localLayoutParams = window.attributes
        localLayoutParams.flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS.inv() and localLayoutParams.flags

        with(tabLayout) {
            setupWithViewPager(viewPager)
            addOnTabSelectedListener(tabSelectedAction, tabSelectedAction)
        }
        with(viewPager) {
            adapter = SimpleFragmentPagerAdapter(
                    supportFragmentManager,
                    listOf(readerPage, editorPage, playerPage),
                    listOf(readerStr, writerStr, playerStr)
            )
            addOnPageChangeListener(this@MainActivity)
        }

        actionMenu.showAction = { showMenu() }
        actionMenu.hideAction = { hideMenu() }

        shade.clicks()
                .subscribe { actionMenu.hideMenu() }

        action.clicks()
                .compose(rxPermissions.ensure(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE))
                .subscribe {
                    actionMenu.hideMenu()
                    if (it) {
                        when (viewPager.currentItem) {
                            0 -> readerPage.actionClick()
                            1 -> editorPage.actionClick()
                            2 -> playerPage.actionClick()
                        }
                    } else {
                        noPermissionSnack.show()
                    }
                }
    }

    private fun showMenu() {
        if (blurEndAnimator.isRunning) {
            blurEndAnimator.cancel()
        }
        if (blurStartAnimator.isRunning) {
            blurStartAnimator.cancel()
        }
        viewPager.isDrawingCacheEnabled = true
        val viewShot: Bitmap = Bitmap.createBitmap(viewPager.drawingCache)
        viewPager.isDrawingCacheEnabled = false
        shade.setImageBitmap(viewShot.blur())
        blurStartAnimator.start()
        shade.visibility = VISIBLE
    }

    private fun hideMenu() {
        if (blurEndAnimator.isRunning) {
            blurEndAnimator.cancel()
        }
        if (blurStartAnimator.isRunning) {
            blurStartAnimator.cancel()
        }
        blurEndAnimator.start()
    }

    private fun addMenu(towards: Int) {
        val floatingButton: FloatingActionButton = FloatingActionButton(this)
        floatingButton.layoutParams = FamLayoutParams(towards)
        actionMenu.addView(floatingButton)
    }

    fun hide() {
        actionMenu.visibility = GONE
    }

    fun show() {
        actionMenu.visibility = VISIBLE
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (viewPager.currentItem) {
            0 -> readerPage.onActivityResult(requestCode, resultCode, data)
            1 -> editorPage.onActivityResult(requestCode, resultCode, data)
            2 -> playerPage.onActivityResult(requestCode, resultCode, data)
        }
    }

    override fun onActivityReenter(resultCode: Int, data: Intent?) {
        super.onActivityReenter(resultCode, data)
        playerPage.onActivityReenter(resultCode, data)
    }


    // below is viewpager's on page change listener
    override fun onPageScrollStateChanged(state: Int) {

    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {

    }

    override fun onPageSelected(position: Int) {
        when (position) {
            0 -> {
                if (readerPage.currentIndex() == 0) {
                    show()
                } else {
                    hide()
                }
            }
            1 -> {
                show()
            }
            2 -> {
                show()
            }
        }
    }
}
